/*
 * Queue.c: Implementation of a wait free queue
 */
#include "LockQueue.h"
#include "CAS.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

inline LockQueue* getQueue(unsigned int numOfThreads){
	LockQueue* queue = NULL;
	queue = (LockQueue*)malloc(sizeof(LockQueue));
	memset(queue, 0, sizeof(LockQueue));
	pthread_mutex_init(&queue->mutex, 0);
	return queue;
}

inline void deleteQueue(LockQueue* queue){
	if (NULL == queue) return;

	Node* currNode;
	while(NULL != queue->head){
		currNode = queue->head;
		queue->head = queue->head->next;
		free(currNode);
	}
	pthread_mutex_destroy(&queue->mutex);
	free(queue);
}

/**
 * Enqueue a new value to the queue
 */
inline void enq(LockQueue* queue, long long myTid, int value) {
	if (NULL == queue) return;

	//Allocate new node
	Node* newNode = (Node*)malloc(sizeof(Node));
	newNode->value = value;
	newNode->next = NULL;

	pthread_mutex_lock(&queue->mutex);
	if (NULL == queue->head){
		queue->head = queue->tail = newNode;
	}
	else{
		queue->tail->next = newNode;
		queue->tail = newNode;
	}
	pthread_mutex_unlock(&queue->mutex);
}

/**
 * Dequeue a node from the queue
 */
inline int deq(LockQueue* queue, long long myTid){
	int res = -1;
	Node* node = NULL;
	if (NULL == queue) return res;

	pthread_mutex_lock(&queue->mutex);
	if (NULL != queue->head){
		node = queue->head;
		queue->head = queue->head->next;
		if (NULL == queue->head)
			queue->tail = NULL;
	}
	pthread_mutex_unlock(&queue->mutex);
	if (node != NULL){
		res = node->value;
		free (node);
	}
	return res;
}

inline void printQueue(LockQueue* queue){
	Node* node = queue->head;
	printf("Queue = ");
	while(node){
		printf("%d, ",node->value);
		node = node->next;
	}
	printf("\n");
}
inline void printQueueSize(LockQueue* queue){
	Node* node = queue->head;
	int size = 0;
	while(node){
		size++;
		node = node->next;
	}
	printf("queue size=%d\n",size);
}
